package common.util;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.IFill;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Property;
import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler;
import com.google.common.collect.Lists;
import common.controller.base.BaseController;
import common.model.po.base.BasePo;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

/**
 * MybatisPlus代码生成器
 *
 * @author 米泽鹏
 * @since 2021-07-28 10:42 上午
 */
@Slf4j
public class MybatisPlusGenerator {

	/**
	 * 业务模块名称<br/>
	 * 改这里！！！
	 */
	// private static final String BUSINESS_MODULE_NAME = "log";
	// private static final String BUSINESS_MODULE_NAME = "gateway";
	// private static final String BUSINESS_MODULE_NAME = "system";
	private static final String BUSINESS_MODULE_NAME = "game";

	/**
	 * 生成文件路径（Windows）
	 */
	private static final String OUTPUT_DIR_WIN = "D:/MybatisPlusGenerator/src/main/java";

	/**
	 * 生成文件路径（MacOS）
	 */
	private static final String OUTPUT_DIR_MAC = "/Users/mizepeng/MybatisPlusGenerator";

	/**
	 * 类作者
	 */
	private static final String AUTHOR = "米泽鹏";

	/**
	 * 常量
	 */
	private static final String COMMON_UPPER_FIRST = "Common";

	/**
	 * 常量
	 */
	private static final String COMMON_LOWER = "common";

	/**
	 * po实体类包路径
	 */
	private static final String ENTITY = "model.po";

	/**
	 * controller包路径
	 */
	private static final String CONTROLLER = "controller";

	/**
	 * Service接口包路径
	 */
	private static final String SERVICE = "service";

	/**
	 * Service实现类包路径
	 */
	private static final String SERVICE_IMPL = "service.impl";

	/**
	 * Mapper接口包路径
	 */
	private static final String MAPPER = "mapper";

	/**
	 * Mapper.xml路径
	 */
	private static final String MAPPER_XML = "mapper.xml";

	public static void main(String[] args) {

		String[] tableNames = scanTableNames();

		// 数据源配置
		DataSourceConfig dsc = new DataSourceConfig.Builder(
				"jdbc:mysql://localhost:3307/satisfactory?rewriteBatchedStatements=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai",
				"root",
				"mzp19940219")
				.schema("mybatis-plus")
				.keyWordsHandler(new MySqlKeyWordsHandler())
				.typeConvert(new MySqlTypeConvert() {
					@Override
					public DbColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
						log.info("转换类型：" + fieldType);
						// 将数据库中datetime转换成date
						if (fieldType.toLowerCase().contains("datetime")) {
							return DbColumnType.DATE;
						}
						if (fieldType.toLowerCase().contains("date")) {
							return DbColumnType.DATE;
						}
						return (DbColumnType) super.processTypeConvert(globalConfig, fieldType);
					}
				})
				.build();

		// 全局配置
		GlobalConfig globalConfig = new GlobalConfig
				.Builder()
				.outputDir(OUTPUT_DIR_WIN)
//				.outputDir(OUTPUT_DIR_MAC)
//				.outputDir(System.getProperty("user.dir") + "/src/main/java")
				.author(AUTHOR)
//				.enableKotlin()
				.enableSwagger()
				.dateType(DateType.ONLY_DATE)
				.commentDate("yyyy-MM-dd aa hh:mm")
				// 生成完毕不自动打开目录
				.disableOpenDir()
				.build();

		// 注入配置
		InjectionConfig injectionConfig = new InjectionConfig.Builder()
				// 向模板文件传递的自定义参数
				.customMap(Collections.singletonMap("businessModuleName", BUSINESS_MODULE_NAME))
				.build();

		// 实体类字段填充配置
		List<IFill> tableFillList = Lists.newArrayList();
		IFill createTimeField = new Property("createTime", FieldFill.INSERT);
		IFill updateTimeField = new Property("updateTime", FieldFill.INSERT_UPDATE);
		tableFillList.add(createTimeField);
		tableFillList.add(updateTimeField);

		// 模板配置
		TemplateConfig commonTemplateConfig = new TemplateConfig
				.Builder()
				.entity("generatorTemplates/entity.java")
				.mapper("generatorTemplates/mapper.java")
				.xml("generatorTemplates/mapper.xml")
				.service("generatorTemplates/service.java")
				.serviceImpl("generatorTemplates/serviceImpl.java")
				// 不生成controller
				.disable(TemplateType.CONTROLLER)
				.build();

		// common模块包配置
		PackageConfig commonPackageConfig = new PackageConfig
				.Builder()
				.parent(COMMON_LOWER)
				.entity(ENTITY)
				.mapper(MAPPER)
				.xml(MAPPER_XML)
				.service(SERVICE)
				.serviceImpl(SERVICE_IMPL)
				.build();

		// common模块策略配置
		StrategyConfig commonStrategyConfig = new StrategyConfig
				.Builder()
				.addInclude(tableNames)
				// 实体类配置
				.entityBuilder()
//				.enableFileOverride()
				.superClass(BasePo.class)
//				.disableSerialVersionUID()
				.enableChainModel()
				.enableLombok()
//				.enableTableFieldAnnotation()
				.enableActiveRecord()
//				.versionColumnName("update_time")
				.versionPropertyName("updateTime")
//				.logicDeleteColumnName("is_deleted")
//				.logicDeletePropertyName("isDeleted")
				.naming(NamingStrategy.underline_to_camel)
				.columnNaming(NamingStrategy.underline_to_camel)
				.addSuperEntityColumns("id", "operator", "create_time", "update_time")
//				.addIgnoreColumns("test1", "test2")
				.addTableFills(tableFillList)
//				.idType(IdType.AUTO)
//				.convertFileName((entityName -> COMMON_UPPER_FIRST + entityName))
//				.formatFileName("%sPo")
				// service配置
				.serviceBuilder()
//				.enableFileOverride()
				.convertServiceFileName((entityName -> COMMON_UPPER_FIRST + entityName + ConstVal.SERVICE))
				.convertServiceImplFileName((entityName -> COMMON_UPPER_FIRST + entityName + ConstVal.SERVICE_IMPL))
				// mapper配置
				.mapperBuilder()
//				.enableFileOverride()
				.convertMapperFileName((entityName -> COMMON_UPPER_FIRST + entityName + ConstVal.MAPPER))
				.convertXmlFileName((entityName -> COMMON_UPPER_FIRST + entityName + ConstVal.MAPPER))
				.build();

		// 代码生成器
		AutoGenerator commonGenerator = new AutoGenerator(dsc);
		commonGenerator.global(globalConfig);
		commonGenerator.injection(injectionConfig);
		commonGenerator.packageInfo(commonPackageConfig);
		commonGenerator.template(commonTemplateConfig);
		commonGenerator.strategy(commonStrategyConfig);
		log.info("开始生成" + COMMON_LOWER + "模块代码");
		commonGenerator.execute(new FreemarkerTemplateEngine());

		// 模板配置
		TemplateConfig businessTemplateConfig = new TemplateConfig
				.Builder()
				.mapper("generatorTemplates/mapper.java")
				.xml("generatorTemplates/mapper.xml")
				.service("generatorTemplates/service.java")
				.serviceImpl("generatorTemplates/serviceImpl.java")
				.controller("generatorTemplates/controller.java")
				// 不生成entity
				.disable(TemplateType.ENTITY)
				.build();

		// 业务模块包配置
		PackageConfig businessPackageConfig = new PackageConfig
				.Builder()
				.parent(BUSINESS_MODULE_NAME)
				.mapper(MAPPER)
				.xml(MAPPER_XML)
				.service(SERVICE)
				.serviceImpl(SERVICE_IMPL)
				.controller(CONTROLLER)
				.build();

		// 业务模块策略配置
		StrategyConfig businessStrategyConfig = new StrategyConfig
				.Builder()
				.addInclude(tableNames)
				// controller配置
				.controllerBuilder()
//				.enableFileOverride()
				.superClass(BaseController.class)
				.convertFileName((entityName -> entityName + ConstVal.CONTROLLER))
				.enableRestStyle()
				.enableHyphenStyle()
				// service配置
				.serviceBuilder()
//				.enableFileOverride()
				.convertServiceFileName((entityName -> entityName + ConstVal.SERVICE))
				.convertServiceImplFileName((entityName -> entityName + ConstVal.SERVICE_IMPL))
				// mapper配置
				.mapperBuilder()
//				.enableFileOverride()
				.convertMapperFileName((entityName -> entityName + ConstVal.MAPPER))
				.convertXmlFileName((entityName -> entityName + ConstVal.MAPPER))
				.build();

		// 代码生成器
		AutoGenerator businessGenerator = new AutoGenerator(dsc);
		businessGenerator.global(globalConfig);
		businessGenerator.injection(injectionConfig);
		businessGenerator.packageInfo(businessPackageConfig);
		businessGenerator.template(businessTemplateConfig);
		businessGenerator.strategy(businessStrategyConfig);
		log.info("开始生成" + BUSINESS_MODULE_NAME + "模块代码");
		businessGenerator.execute(new FreemarkerTemplateEngine());

	}

	private static String[] scanTableNames() {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入表名，多个请用英文逗号隔开：");
		if (scanner.hasNextLine()) {
			String tableNames = scanner.nextLine();
			if (StringUtils.isNotBlank(tableNames)) {
				return Arrays.stream(tableNames.split(",")).map(String::trim).toArray(String[]::new);
			}
		}
		throw new MybatisPlusException("请输入正确的表名，多个请用英文逗号隔开");
	}

}
